package cn.com.cennavi.ICEAcess;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

import cn.com.cennavi.bean.ReadResultDataSampleFromDBInputParam;
import cn.com.cennavi.bean.ReadResultDataSampleFromDBOutputResult;
import cn.com.cennavi.config.ReadResultDataSampleFromDBConfig;

/**
 * 
 * @Description
 * @author buf
 * @date 2017年3月3日 上午11:26:10
 */
public class ReadResultDataSampleFromDB {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		System.setProperty("hadoop.home.dir", "d:\\hadoop-2.4.0");
		ReadResultDataSampleFromDBInputParam askData = new ReadResultDataSampleFromDBInputParam();
		ReadResultDataSampleFromDBOutputResult returnData = new ReadResultDataSampleFromDBOutputResult();
		askData.userID = "azkaban";
		askData.projectID = "odModel_odNum";
		askData.filePath = "hdfs://nujhadoop/test/minlab/od/azkaban_odModel_odNum_1488508675683";
		askData.topN=10;
		// 得到askData返回结果
		getData(askData.topN, askData, askData.filePath, returnData);
		getResultDataID(askData.userID, askData.projectID, askData, returnData);
		returnData.toPrintString();

	}

	/**
	 * 需要修改
	 * 
	 * @Description
	 * @author Thinkpad
	 * @param userID
	 * @param projectID
	 * @param askData
	 * @param returnData
	 */
	private static void getResultDataID(String userID, String projectID, ReadResultDataSampleFromDBInputParam askData, ReadResultDataSampleFromDBOutputResult returnData) {
		// TODO Auto-generated method stub
		long time = new Date().getTime();
		returnData.resultDataID = userID + "_" + time;
	}

	/**
	 * 需要修改
	 * 
	 * @Description
	 * @author Thinkpad
	 * @param userID
	 * @param projectID
	 * @param topN
	 * @param askData
	 * @param filePath
	 * @param returnData
	 * @throws Exception
	 */
	private static void getData(int topN, ReadResultDataSampleFromDBInputParam askData, String filePath, ReadResultDataSampleFromDBOutputResult returnData) throws Exception {
		// TODO Auto-generated method stub
		String fileName = "";
		String[] arr = askData.projectID.split("\\_");
		String modelClass = getMpdelClass(askData);
		switch (modelClass) {
		case "hotSpot":
			// 请求的odModel_hotSpot
			// 要返回hotSpot样例数据，要返回hotSpot数据规格
			fileName = ReadResultDataSampleFromDBConfig.getHotSpotPath();// "D:\\data\\dataformat\\hotSpot.xls";
			break;
		case "odNum":
			// 请求的odModel_odNum
			// 要返回odNum样例数据，要返回odNum数据规格
			fileName = ReadResultDataSampleFromDBConfig.getOdNumPath();// "D:\\data\\dataformat\\odNum.xls";
			break;
		}
		int outFlag = 2;// Integer.parseInt(arr[7]);
		// 读取元数据对应的配置文件
		readExcelFile(fileName, askData, returnData);
		getSampleData(topN, askData, outFlag, filePath, returnData);

	}

	private static String getMpdelClass(ReadResultDataSampleFromDBInputParam askData) {
		// TODO Auto-generated method stub
		String[] arr = askData.filePath.split("/");
		int length = arr.length;
		if (length != 0) {
			return arr[length - 1].split("\\_")[2];
		}
		return null;
	}

	/**
	 * 需要修改 返回编码参考http://www.cnblogs.com/ctaixw/p/5075727.html
	 * 
	 * @Description
	 * @author Thinkpad
	 * @param userID
	 * @param projectID
	 * @param topN
	 * @param askData
	 * @param outFlag
	 * @param filePath
	 * @param returnData
	 * @throws Exception
	 */
	private static void getSampleData(int topN, ReadResultDataSampleFromDBInputParam askData, int outFlag, String filePath, ReadResultDataSampleFromDBOutputResult returnData) throws Exception {
		// TODO Auto-generated method stub
		ArrayList<String> dataLsit = new ArrayList<String>();
		int i = topN;
		String nowoutPath = "";
		switch (outFlag) {
		case 1:
			// 输出到kafka，outFlagAndPath为topic
			break;
		case 2:
			// 输出到hdfs
			nowoutPath = filePath;
			break;
		case 3:
			// 到mysql

			break;
		default:
			break;
		}
		if (isGoodFile(nowoutPath)) {
			returnData.sampleData = getDataTopN(nowoutPath, topN, outFlag);
			returnData.errCode = 200;
			returnData.errMsg = "good job!";
		} else {
			returnData.errCode = 404;
			returnData.errMsg = "filePath:" + nowoutPath + " is not exist!";
		}

	}

	private static ArrayList<String> getDataTopN(String outPath, int topN, int outFlag) throws IllegalArgumentException, IOException {
		// TODO Auto-generated method stub
		ArrayList<String> returnList = new ArrayList<String>();
		Configuration conf = new Configuration();
		ArrayList<String> fileList = getFilePaths(outPath, conf);

		for (String dsf : fileList) {
			if (returnList.size() < topN) {
				BufferedReader bufferedReader = null;
				FileSystem fs = FileSystem.get(URI.create(dsf), conf);
				FSDataInputStream hdfsInStream = fs.open(new Path(dsf));

				bufferedReader = new BufferedReader(new InputStreamReader(hdfsInStream));
				String lineTxt = "";
				while ((lineTxt = bufferedReader.readLine()) != null) {
					if (returnList.size() < topN) {
						returnList.add(lineTxt);
					} else {
						bufferedReader.close();
						break;
					}

				}
			}
		}

		return returnList;
	}

	private static ArrayList<String> getFilePaths(String outPath, Configuration conf) throws FileNotFoundException, IllegalArgumentException, IOException {
		// TODO Auto-generated method stub
		ArrayList<String> dataList = new ArrayList<String>();
		FileSystem fs = FileSystem.get(URI.create(outPath), conf);
		FileStatus fileList[] = fs.listStatus(new Path(outPath));
		int size = fileList.length;
		for (int i = 0; i < size; i++) {
			String fileName = fileList[i].getPath().getName();
			if (fileName.startsWith("part-")) {
				dataList.add(fileList[i].getPath().toString());
			}
		}
		fs.close();
		return dataList;
	}

	/**
	 * 判断路径是不是存在 需要修改
	 * 
	 * @Description
	 * @author buf
	 * @param filePath
	 * @return
	 * @throws Exception
	 */
	private static boolean isGoodFile(String filePath) throws Exception {
		// TODO Auto-generated method stub
		switch (filePath.substring(0, 4)) {
		case "kafk":
			// 输出到kafka，outFlagAndPath为topic
			// 扩展
			break;
		case "hdfs":
			// 输出到hdfs
			return testExists(filePath);
		case "mysq":
			// 到mysql
			// 扩展
			break;
		default:
			break;
		}
		return false;
	}

	public static boolean testExists(String hdfsPath) throws Exception {

		Configuration conf = new Configuration();

		FileSystem hdfs = FileSystem.get(conf);
		Path dst = new Path(hdfsPath);

		boolean ok = hdfs.exists(dst);
		System.out.println(ok ? hdfsPath + "文件存在" : hdfsPath + "文件不存在");
		return ok;
	}

	private static void readExcelFile(String fileName, ReadResultDataSampleFromDBInputParam askData, ReadResultDataSampleFromDBOutputResult returnData) throws FileNotFoundException, IOException {
		// TODO Auto-generated method stub
		StringBuffer sb = new StringBuffer();
		File file = new File(fileName);
		String[][] result = getData(file, 1);
		int rowLength = result.length;
		for (int i = 0; i < rowLength; i++) {
			for (int j = 0; j < result[i].length; j++) {
				// System.out.print(result[i][j] + "\t");
				sb.append(result[i][j] + "\t");

			}
			// System.out.println();
			sb.append("\r");
		}
		returnData.metadata = sb.toString().getBytes();
	}

	/**
	 * 读取Excel的内容，第一维数组存储的是一行中格列的值，二维数组存储的是多少个行
	 * 
	 * @param file
	 *            读取数据的源Excel
	 * @param ignoreRows
	 *            读取数据忽略的行数，比喻行头不需要读入 忽略的行数为1
	 * @return 读出的Excel中数据的内容
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public static String[][] getData(File file, int ignoreRows) throws FileNotFoundException, IOException {
		List<String[]> result = new ArrayList<String[]>();
		int rowSize = 0;
		BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
		// 打开HSSFWorkbook
		POIFSFileSystem fs = new POIFSFileSystem(in);
		HSSFWorkbook wb = new HSSFWorkbook(fs);
		HSSFCell cell = null;
		for (int sheetIndex = 0; sheetIndex < wb.getNumberOfSheets(); sheetIndex++) {
			HSSFSheet st = wb.getSheetAt(sheetIndex);
			// 第一行为标题，不取
			for (int rowIndex = ignoreRows; rowIndex <= st.getLastRowNum(); rowIndex++) {
				HSSFRow row = st.getRow(rowIndex);
				if (row == null) {
					continue;
				}
				int tempRowSize = row.getLastCellNum() + 1;
				if (tempRowSize > rowSize) {
					rowSize = tempRowSize;
				}
				String[] values = new String[rowSize];
				Arrays.fill(values, "");
				boolean hasValue = false;
				for (short columnIndex = 0; columnIndex <= row.getLastCellNum(); columnIndex++) {
					String value = "";
					cell = row.getCell(columnIndex);
					if (cell != null) {
						// 注意：一定要设成这个，否则可能会出现乱码
						// cell.setEncoding(HSSFCell.ENCODING_UTF_16);
						cell.setCellNum(HSSFCell.ENCODING_UTF_16);
						switch (cell.getCellType()) {
						case HSSFCell.CELL_TYPE_STRING:
							value = cell.getStringCellValue();
							break;
						case HSSFCell.CELL_TYPE_NUMERIC:
							if (HSSFDateUtil.isCellDateFormatted(cell)) {
								Date date = cell.getDateCellValue();
								if (date != null) {
									value = new SimpleDateFormat("yyyy-MM-dd").format(date);
								} else {
									value = "";
								}
							} else {
								value = new DecimalFormat("0").format(cell.getNumericCellValue());
							}
							break;
						case HSSFCell.CELL_TYPE_FORMULA:
							// 导入时如果为公式生成的数据则无值
							if (!cell.getStringCellValue().equals("")) {
								value = cell.getStringCellValue();
							} else {
								value = cell.getNumericCellValue() + "";
							}
							break;
						case HSSFCell.CELL_TYPE_BLANK:
							break;
						case HSSFCell.CELL_TYPE_ERROR:
							value = "";
							break;
						case HSSFCell.CELL_TYPE_BOOLEAN:
							value = (cell.getBooleanCellValue() == true ? "Y" : "N");
							break;
						default:
							value = "";
						}
					}
					if (columnIndex == 0 && value.trim().equals("")) {
						break;
					}
					values[columnIndex] = rightTrim(value);
					hasValue = true;
				}

				if (hasValue) {
					result.add(values);
				}
			}
		}
		in.close();
		String[][] returnArray = new String[result.size()][rowSize];
		for (int i = 0; i < returnArray.length; i++) {
			returnArray[i] = (String[]) result.get(i);
		}
		return returnArray;
	}

	/**
	 * 去掉字符串右边的空格
	 * 
	 * @param str
	 *            要处理的字符串
	 * @return 处理后的字符串
	 */
	public static String rightTrim(String str) {
		if (str == null) {
			return "";
		}
		int length = str.length();
		for (int i = length - 1; i >= 0; i--) {
			if (str.charAt(i) != 0x20) {
				break;
			}
			length--;
		}
		return str.substring(0, length);
	}
}
